#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <thread>
#include "ring-buffer.h"

CircularBuffer buffer;

// 初始化环形缓冲区
void initCircularBuffer(CircularBuffer *buffer)
{
    buffer->data = (char *)malloc(BUFFER_SIZE * sizeof(char)); // 动态分配数据数组内存
    buffer->front = 0;
    buffer->rear = 0;
    buffer->count = 0;
}

// 销毁环形缓冲区
void destroyCircularBuffer(CircularBuffer *buffer)
{
    free(buffer->data); // 释放数据数组内存
}

void test1()
{
    bool flag = true;
    while (flag)
    { // 写入数据
        int data1 = 10;
        flag = writeData(&buffer, &data1, sizeof(int)).len == sizeof(int);

        if (flag)
        {
            char data2[] = "hello world";
            flag = writeData(&buffer, data2, strlen(data2) + 1).len == (strlen(data2) + 1);
        }
    }

    flag = true;
    while (flag)
    { // 读取数据
        DataHeader header;

        int data1 = 0;
        flag = readData(&buffer, &data1, &header);
        if (flag)
        {
            if (header.len != sizeof(int))
            {
                printf("ERROR!\n");
            }
            if (data1 != 10)
                printf("ERROR! 读取的第一个数据：%d\n", data1);
        }

        char data2[1024] = {0};
        flag = readData(&buffer, data2, &header);
        if (flag)
        {
            if (strcmp("hello world", data2) != 0)
                printf("ERROR! 读取的第二个数据：%s\n", data2);
        }
    }
    printf("test1 done\n");
}

uint64_t cal_checksum(uint64_t *data, size_t len)
{
    uint64_t checksum = 0;
    for (size_t i = 0; i < len; i++)
    {
        checksum ^= data[i];
    }
    return checksum;
}

void writer()
{
    // 设置种子
    srand((unsigned)time(NULL));
    while (true)
    { // 生成随机数据
        int len = rand() % BUFFER_SIZE / 64;
        uint64_t *data = (uint64_t *)malloc(len * sizeof(uint64_t));
        for (int i = 0; i < len - 1; i++)
        {
            data[i] = rand();
        }
        data[len - 1] = cal_checksum(data, len - 1);
        DataHeader header = writeData(&buffer, data, len * sizeof(uint64_t));
        free(data);
        if (header.len == 0)
        {
            break;
        }
    }
}

void reader()
{
    while (true)
    {
        DataHeader header;
        char *data = (char *)malloc(BUFFER_SIZE * sizeof(char) * 2);
        if (readData(&buffer, data, &header))
        {
            uint64_t *data64 = (uint64_t *)data;
            uint64_t checksum = cal_checksum(data64, header.len / sizeof(uint64_t) - 1);
            if (checksum != data64[header.len / sizeof(uint64_t) - 1])
            {
                printf("ERROR! 校验和不匹配\n");
            }
            free(data);
        }
        else
        {
            free(data);
            break;
        }
    }
}

void test2()
{
    for (int i = 0; i < 100; i++)
    {
        writer();
        reader();
    }
    printf("test2 done\n");
}

void test3()
{
    auto w = []()
    {
        srand((unsigned)time(NULL));
        for (int i = 0; i < 10000; i++)
        {
            int sleep_time = rand() % 20;
            std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
            writer();
        }
    };
    auto r = []()
    {
        srand((unsigned)time(NULL));
        for (int i = 0; i < 10000; ++i)
        {
            int sleep_time = rand() % 20;
            std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
            reader();
        }
    };
    std::thread t1(w);
    std::thread t2(r);
    t1.join();
    t2.join();
    printf("test3 done\n");
}

int main()
{
    initCircularBuffer(&buffer);

    test1();

    test2();

    test3();

    // 销毁环形缓冲区
    destroyCircularBuffer(&buffer);

    return 0;
}
